#pragma once
#include <string>
#include <iostream>

#include "DataStructure/Input/Node/NodeData.h"
#include "DataStructure/Input/Solver/DOFDirections.h"
#include "DataStructure/Input/Solver/Subcase.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/Database/DatabaseFactory.h"
#include "DBManager/IService/Input/Constraint/ISPCService.h"
#include "DBManager/IService/Input/Load/IFORCEService.h"
#include "DBManager/IService/Input/Element/IElementService.h"
#include "DBManager/IService/Input/Material/IIsotropicMaterialService.h"
#include "DBManager/IService/Input/Node/INodeService.h"
#include "DBManager/IService/Input/Property/IPRODService.h"
#include "DBManager/IService/Input/Subcase/ISubcaseService.h"

using SG::DataStructure::FEM::DOFDirections;
using SG::DataStructure::FEM::DofSet2Int;
using namespace SG::DBManager;
extern std::shared_ptr<DBServiceFactory> DB_SERVICEFACTORY;

/// 两杆桁架模型数据
class Link_TwoEle
{
  public:
    Link_TwoEle ()
    {
        DB_SERVICEFACTORY->ClearDatabase ();
        Input (DB_SERVICEFACTORY);
    }

    /// @brief 写入模型数据
    void               Input (const DBServiceFactorySP dbServiceFactory);
    DBServiceFactorySP GetModel ()
    {
        return DB_SERVICEFACTORY;
    }
};

void Link_TwoEle::Input (const DBServiceFactorySP dbServiceFactory)
{
    // 节点写入
    {
        SG::DataStructure::FEM::NodeData node;
        node.m_defCoord  = 0;
        node.m_dispCoord = 0;
        node.m_id        = 1;
        node.m_x[0]      = 0.0;
        node.m_x[1]      = 0.0;
        node.m_x[2]      = 0.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 2;
        node.m_x[0] = 2.0;
        node.m_x[1] = 0.0;
        node.m_x[2] = 0.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
        node.m_id   = 3;
        node.m_x[0] = 1.0;
        node.m_x[1] = 1.0;
        node.m_x[2] = 0.0;
        dbServiceFactory->get<INodeService> ()->Add (node);
    }

    // 材料写入
    {
        SG::DataStructure::FEM::IsotropicMaterial material;
        material.m_id = 1;
        material.m_E  = 2.95e5;
        material.m_nu = 0.2;
        material.m_G  = material.m_E / 2.0 * (1.0 + material.m_nu);
        dbServiceFactory->get<IIsotropicMaterialService> ()->Add (material);
    }

    // 截面属性写入
    {
        SG::DataStructure::FEM::PRODData prod;
        prod.m_id            = 1;
        prod.m_mId           = 1;
        prod.m_area          = 0.5;
        prod.m_torsionFactor = 0.0;
        dbServiceFactory->get<IPRODService> ()->Add (prod);
    }

    // 单元写入
    {
        SG::DataStructure::FEM::CRODData rodEle;
        rodEle.m_id   = 1;
        rodEle.m_pId  = 1;
        rodEle.m_g[0] = 1;
        rodEle.m_g[1] = 3;
        dbServiceFactory->get<IElementService> ()->Add (rodEle);

        rodEle.m_id   = 2;
        rodEle.m_pId  = 1;
        rodEle.m_g[0] = 2;
        rodEle.m_g[1] = 3;
        dbServiceFactory->get<IElementService> ()->Add (rodEle);
    }

    SG::Utility::SGParameter mulitiSubcase;
    // 工况1
    {
        SG::DataStructure::FEM::Subcase subcase;
        // subcase.m_id   = 1;
        // subcase.m_spc  = 1;
        // subcase.m_load = 1;
        subcase.AddParameter({"SUBCASE","1"});
        subcase.AddParameter({"SOL","101"});
        subcase.AddParameter({"SPC","1"});
        subcase.AddParameter({"LOAD","1"});
        mulitiSubcase.AddValue("1", subcase.Data());

        // 节点固定约束
        {
            SG::DataStructure::FEM::SPCData spc;
            spc.m_sId = 1;
            spc.m_g   = 1;
            spc.m_c   = DofSet2Int ({ DOFDirections::DOF_Ux, DOFDirections::DOF_Uy, DOFDirections::DOF_Uz });
            spc.m_d   = 0;
            dbServiceFactory->get<ISPCService> ()->Add (spc);

            spc.m_g = 2;
            spc.m_c = DofSet2Int ({ DOFDirections::DOF_Ux, DOFDirections::DOF_Uy, DOFDirections::DOF_Uz });
            spc.m_d = 0.0;
            dbServiceFactory->get<ISPCService> ()->Add (spc);
            // 平面桁架，约束面外唯一自由度
            spc.m_g = 3;
            spc.m_c = DofSet2Int ({ DOFDirections::DOF_Uz });
            spc.m_d = 0;
            dbServiceFactory->get<ISPCService> ()->Add (spc);
        }

        // 加入载荷向量
        {
            SG::DataStructure::FEM::FORCEData force;
            force.m_sId         = 1;
            force.m_coordSysmId = 0;
            force.m_nodeId      = 3;
            force.m_load[0]     = 1.0;
            force.m_load[1]     = 2.0;
            force.m_factor      = 1.5;

            dbServiceFactory->get<IFORCEService> ()->Add (force);
        }
    }

    // 工况2 传热
    {
        SG::DataStructure::FEM::Subcase subcase;
        // subcase.m_id   = 2;
        // subcase.m_spc  = 2;
        // subcase.m_load = 1;
        // dbServiceFactory->get<ISubcaseService> ()->Add (subcase);
        subcase.AddParameter({"SUBCASE","2"});
        subcase.AddParameter({"SOL","101"});
        subcase.AddParameter({"SPC","2"});
        subcase.AddParameter({"LOAD","1"});
        mulitiSubcase.AddValue("2", subcase.Data());

        // 节点固定约束
        {
            SG::DataStructure::FEM::SPCData spc;
            spc.m_sId = 2;
            spc.m_g   = 1;
            spc.m_c   = DofSet2Int ({ DOFDirections::DOF_Ux });
            spc.m_d   = 0;
            dbServiceFactory->get<ISPCService> ()->Add (spc);

            spc.m_g = 2;
            spc.m_c = DofSet2Int ({ DOFDirections::DOF_Ux });
            spc.m_d = 0.0;
            dbServiceFactory->get<ISPCService> ()->Add (spc);
            // 平面桁架，约束面外唯一自由度
        }
    }

    dbServiceFactory->get<ISubcaseService> ()->Initial (mulitiSubcase);

}